/*
 * ArtistPanel.java
 *
 * Created on June 11, 2005, 12:30 PM
 */
package com.bff.slimserver.musicjukebox.ui;

import com.bff.slimserver.music.MusicObjects;
import com.bff.bjj.ui.component.ColorProperties;
import java.util.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import com.bff.bjj.ui.component.BJJPanel;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import org.bff.slimserver.SlimDatabase;
import org.bff.slimserver.SlimPlaylist;
import org.bff.slimserver.musicobjects.SlimAlbum;
import org.bff.slimserver.musicobjects.SlimArtist;
import org.bff.slimserver.musicobjects.SlimGenre;

/**
 *
 * @author  Bill
 */
public class ExplorerTreePanel
        extends BJJPanel
        implements ExplorerIface {

    private DefaultMutableTreeNode topYearNode = new DefaultMutableTreeNode("Year");
    private DefaultTreeModel treeYearModel = new DefaultTreeModel(topYearNode);
    private DefaultMutableTreeNode topGenreNode = new DefaultMutableTreeNode("Genre");
    private DefaultTreeModel treeGenreModel = new DefaultTreeModel(topGenreNode);
    private DefaultMutableTreeNode topArtistNode = new DefaultMutableTreeNode("Artist");
    private DefaultTreeModel treeArtistModel = new DefaultTreeModel(topArtistNode);
    private SlimDatabase database;
    private SlimPlaylist playlist;
    private static final String CARD_ARTIST = "CARD_ARTIST";
    private static final String CARD_GENRE = "CARD_GENRE";
    private static final String CARD_YEAR = "CARD_YEAR";
    private String cardShowing;

    private SongListTablePanel songListTablePanel;

    private static final int START_DIVIDER_LOCATION = 400;

    public ExplorerTreePanel() {
    }

    /** Creates new form ArtistPanel */
    public ExplorerTreePanel(SlimDatabase database, SlimPlaylist playlist) {
        this.database = database;
        this.playlist = playlist;

        songListTablePanel = new SongListTablePanel();

        initComponents();

        jPanel1.add(songListTablePanel, BorderLayout.CENTER);
        
        mainSplitPane.setDividerLocation(400);

        showList(CARD_ARTIST);
        setCardShowing(CARD_ARTIST);

        createNodes();

        artistTree.addTreeSelectionListener(new TreeSelectionListener() {

            public void valueChanged(TreeSelectionEvent tse) {
                nodeArtistSelected(tse);
            }
        });

        yearTree.addTreeSelectionListener(new TreeSelectionListener() {

            public void valueChanged(TreeSelectionEvent tse) {
                nodeYearSelected(tse);
            }
        });

        genreTree.addTreeSelectionListener(new TreeSelectionListener() {

            public void valueChanged(TreeSelectionEvent tse) {
                nodeGenreSelected(tse);
            }
        });

        loadProgressBar.setVisible(false);

        ((ExplorerButton) btnArtist).setSelectedBackground();

        if (mainSplitPane.getDividerLocation() < START_DIVIDER_LOCATION) {
            mainSplitPane.setDividerLocation(START_DIVIDER_LOCATION);
        }
    }

    private void createNodes() {
        createArtistNodes(topArtistNode);
        createYearNodes(topYearNode);
        createGenreNodes(topGenreNode);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainSplitPane = new javax.swing.JSplitPane();
        jPanel2 = new javax.swing.JPanel();
        jPanel3 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        yearTree = new javax.swing.JTree(treeYearModel);
        treeScrollPane = new javax.swing.JScrollPane();
        artistTree = new javax.swing.JTree(treeArtistModel);
        jScrollPane2 = new javax.swing.JScrollPane();
        genreTree = new javax.swing.JTree(treeGenreModel);
        jPanel8 = new ExplorerSelectPanel();
        btnArtist = new ExplorerButton();
        btnYear = new ExplorerButton();
        btnGenre = new ExplorerButton();
        loadProgressBar = new javax.swing.JProgressBar();
        jPanel1 = new BJJPanel();

        setLayout(new java.awt.BorderLayout());

        jPanel2.setLayout(new java.awt.BorderLayout());

        jPanel3.setLayout(new java.awt.CardLayout());

        yearTree.setShowsRootHandles(true);
        yearTree.addTreeWillExpandListener(new javax.swing.event.TreeWillExpandListener() {
            public void treeWillCollapse(javax.swing.event.TreeExpansionEvent evt)throws javax.swing.tree.ExpandVetoException {
            }
            public void treeWillExpand(javax.swing.event.TreeExpansionEvent evt)throws javax.swing.tree.ExpandVetoException {
                yearTreeTreeWillExpand(evt);
            }
        });
        jScrollPane1.setViewportView(yearTree);

        jPanel3.add(jScrollPane1, "CARD_YEAR");

        treeScrollPane.setPreferredSize(new java.awt.Dimension(200, 322));

        artistTree.setShowsRootHandles(true);
        artistTree.addTreeWillExpandListener(new javax.swing.event.TreeWillExpandListener() {
            public void treeWillCollapse(javax.swing.event.TreeExpansionEvent evt)throws javax.swing.tree.ExpandVetoException {
            }
            public void treeWillExpand(javax.swing.event.TreeExpansionEvent evt)throws javax.swing.tree.ExpandVetoException {
                treeWillExpanded(evt);
            }
        });
        treeScrollPane.setViewportView(artistTree);

        jPanel3.add(treeScrollPane, "CARD_ARTIST");

        genreTree.setShowsRootHandles(true);
        genreTree.addTreeWillExpandListener(new javax.swing.event.TreeWillExpandListener() {
            public void treeWillCollapse(javax.swing.event.TreeExpansionEvent evt)throws javax.swing.tree.ExpandVetoException {
            }
            public void treeWillExpand(javax.swing.event.TreeExpansionEvent evt)throws javax.swing.tree.ExpandVetoException {
                genreTreeTreeWillExpand(evt);
            }
        });
        jScrollPane2.setViewportView(genreTree);

        jPanel3.add(jScrollPane2, "CARD_GENRE");

        jPanel2.add(jPanel3, java.awt.BorderLayout.CENTER);

        jPanel8.setMaximumSize(new java.awt.Dimension(32767, 28));
        jPanel8.setPreferredSize(new java.awt.Dimension(83, 27));
        jPanel8.setLayout(new java.awt.GridBagLayout());

        btnArtist.setFont(new java.awt.Font("Tahoma", 1, 12));
        btnArtist.setForeground(new java.awt.Color(255, 255, 255));
        btnArtist.setText("Artists");
        btnArtist.setMargin(new java.awt.Insets(0, 0, 0, 0));
        btnArtist.setMaximumSize(new java.awt.Dimension(75, 18));
        btnArtist.setMinimumSize(new java.awt.Dimension(75, 18));
        btnArtist.setPreferredSize(new java.awt.Dimension(75, 18));
        btnArtist.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnArtistActionPerformed(evt);
            }
        });
        jPanel8.add(btnArtist, new java.awt.GridBagConstraints());

        btnYear.setFont(new java.awt.Font("Tahoma", 1, 12));
        btnYear.setForeground(new java.awt.Color(255, 255, 255));
        btnYear.setText("Years");
        btnYear.setMargin(new java.awt.Insets(0, 0, 0, 0));
        btnYear.setMaximumSize(new java.awt.Dimension(75, 18));
        btnYear.setMinimumSize(new java.awt.Dimension(75, 18));
        btnYear.setPreferredSize(new java.awt.Dimension(75, 18));
        btnYear.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnYearActionPerformed(evt);
            }
        });
        jPanel8.add(btnYear, new java.awt.GridBagConstraints());

        btnGenre.setFont(new java.awt.Font("Tahoma", 1, 12));
        btnGenre.setForeground(new java.awt.Color(255, 255, 255));
        btnGenre.setText("Genres");
        btnGenre.setMargin(new java.awt.Insets(0, 0, 0, 0));
        btnGenre.setMaximumSize(new java.awt.Dimension(75, 18));
        btnGenre.setMinimumSize(new java.awt.Dimension(75, 18));
        btnGenre.setPreferredSize(new java.awt.Dimension(75, 18));
        btnGenre.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnGenreActionPerformed(evt);
            }
        });
        jPanel8.add(btnGenre, new java.awt.GridBagConstraints());

        jPanel2.add(jPanel8, java.awt.BorderLayout.NORTH);

        loadProgressBar.setIndeterminate(true);
        loadProgressBar.setString("Loading");
        loadProgressBar.setStringPainted(true);
        jPanel2.add(loadProgressBar, java.awt.BorderLayout.SOUTH);

        mainSplitPane.setLeftComponent(jPanel2);

        jPanel1.setLayout(new java.awt.BorderLayout());
        mainSplitPane.setRightComponent(jPanel1);

        add(mainSplitPane, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents

    private void loadAlbum(SlimAlbum album) {
        songListTablePanel.setAlbum(album);
    }

    private void treeWillExpanded(javax.swing.event.TreeExpansionEvent evt) {//GEN-FIRST:event_treeWillExpanded
        SlimArtist artist = null;
        
        DefaultMutableTreeNode albumNode = null;
        DefaultMutableTreeNode artistNode = null;

        loadProgressBar.setVisible(true);
        
        
        try {
            Thread.sleep(10000);
        } catch (InterruptedException ex) {
            Logger.getLogger(ExplorerTreePanel.class.getName()).log(Level.SEVERE, null, ex);
        }


        try {
            createArtistNodes(topArtistNode);   //in case of any changes
            Object selObject = ((DefaultMutableTreeNode) evt.getPath().getPathComponent(1)).getUserObject();
            artistNode = (DefaultMutableTreeNode) evt.getPath().getLastPathComponent();

            artist = ((SlimArtist) selObject);
            List<SlimAlbum> albumList =
                    new ArrayList<SlimAlbum>(getDatabase().listAlbumsForArtist(artist));
            artistNode.removeAllChildren();
            for (SlimAlbum album : albumList) {
                albumNode = new DefaultMutableTreeNode(album);
                artistNode.add(albumNode);
            }
        } catch (IllegalArgumentException iae) {
            //means first node opened so ignore
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            loadProgressBar.setVisible(false);
        }
    }//GEN-LAST:event_treeWillExpanded

    private void btnArtistActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnArtistActionPerformed
        ((ExplorerButton) btnArtist).setSelectedBackground();
        ((ExplorerButton) btnGenre).setUnselectedBackground();
        ((ExplorerButton) btnYear).setUnselectedBackground();
        showList(CARD_ARTIST);
}//GEN-LAST:event_btnArtistActionPerformed

    private void btnYearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnYearActionPerformed
        ((ExplorerButton) btnArtist).setUnselectedBackground();
        ((ExplorerButton) btnGenre).setUnselectedBackground();
        ((ExplorerButton) btnYear).setSelectedBackground();
        showList(CARD_YEAR);
}//GEN-LAST:event_btnYearActionPerformed

    private void btnGenreActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGenreActionPerformed
        ((ExplorerButton) btnArtist).setUnselectedBackground();
        ((ExplorerButton) btnGenre).setSelectedBackground();
        ((ExplorerButton) btnYear).setUnselectedBackground();
        showList(CARD_GENRE);
}//GEN-LAST:event_btnGenreActionPerformed

    private void genreTreeTreeWillExpand(javax.swing.event.TreeExpansionEvent evt)throws javax.swing.tree.ExpandVetoException {//GEN-FIRST:event_genreTreeTreeWillExpand
        SlimGenre genre = null;

        DefaultMutableTreeNode albumNode = null;
        DefaultMutableTreeNode genreNode = null;

        loadProgressBar.setVisible(true);
        try {
            createGenreNodes(topGenreNode);   //in case of any changes
            Object selObject = ((DefaultMutableTreeNode) evt.getPath().getPathComponent(1)).getUserObject();
            genreNode = (DefaultMutableTreeNode) evt.getPath().getLastPathComponent();

            genre = ((SlimGenre) selObject);
            List<SlimAlbum> albumList =
                    new ArrayList<SlimAlbum>(getDatabase().listAlbumsForGenre(genre));
            genreNode.removeAllChildren();
            for (SlimAlbum album : albumList) {
                albumNode = new DefaultMutableTreeNode(album);
                genreNode.add(albumNode);
            }
        } catch (IllegalArgumentException iae) {
            //means first node opened so ignore
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            loadProgressBar.setVisible(false);
        }
    }//GEN-LAST:event_genreTreeTreeWillExpand

    private void yearTreeTreeWillExpand(javax.swing.event.TreeExpansionEvent evt)throws javax.swing.tree.ExpandVetoException {//GEN-FIRST:event_yearTreeTreeWillExpand
        String year = null;

        DefaultMutableTreeNode albumNode = null;
        DefaultMutableTreeNode yearNode = null;

        loadProgressBar.setVisible(true);
        try {
            createGenreNodes(topGenreNode);   //in case of any changes
            Object selObject = ((DefaultMutableTreeNode) evt.getPath().getPathComponent(1)).getUserObject();
            yearNode = (DefaultMutableTreeNode) evt.getPath().getLastPathComponent();

            year = ((String) selObject);
            List<SlimAlbum> albumList =
                    new ArrayList<SlimAlbum>(getDatabase().listAlbumsForYear(year));
            yearNode.removeAllChildren();
            for (SlimAlbum album : albumList) {
                albumNode = new DefaultMutableTreeNode(album);
                yearNode.add(albumNode);
            }
        } catch (IllegalArgumentException iae) {
            //means first node opened so ignore
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            loadProgressBar.setVisible(false);
        }
    }//GEN-LAST:event_yearTreeTreeWillExpand

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTree artistTree;
    private javax.swing.JButton btnArtist;
    private javax.swing.JButton btnGenre;
    private javax.swing.JButton btnYear;
    private javax.swing.JTree genreTree;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel8;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JProgressBar loadProgressBar;
    private javax.swing.JSplitPane mainSplitPane;
    private javax.swing.JScrollPane treeScrollPane;
    private javax.swing.JTree yearTree;
    // End of variables declaration//GEN-END:variables

    private void createArtistNodes(DefaultMutableTreeNode top) {

        DefaultMutableTreeNode artistNode = null;
        DefaultMutableTreeNode albumNode = null;
        List<SlimArtist> artistList = null;

        try {
            MusicObjects.refreshArtists();
            
            artistList = new ArrayList<SlimArtist>(MusicObjects.getArtists());
            //java.util.Collections.sort(artistList);
            top.removeAllChildren();

            for (SlimArtist a : artistList) {
                artistNode = new DefaultMutableTreeNode(a);
                top.add(artistNode);
                albumNode = new DefaultMutableTreeNode("Temp");
                artistNode.add(albumNode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void createYearNodes(DefaultMutableTreeNode top) {

        DefaultMutableTreeNode yearNode = null;
        DefaultMutableTreeNode albumNode = null;
        List<String> yearList = null;

        try {
            yearList = new ArrayList<String>(getDatabase().getYears());
            yearList.remove("0");
            
            //java.util.Collections.sort(artistList);
            top.removeAllChildren();

            for (String y : yearList) {
                yearNode = new DefaultMutableTreeNode(y);
                top.add(yearNode);
                albumNode = new DefaultMutableTreeNode("Temp");
                yearNode.add(albumNode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void createGenreNodes(DefaultMutableTreeNode top) {

        DefaultMutableTreeNode genreNode = null;
        DefaultMutableTreeNode albumNode = null;
        List<SlimGenre> genreList = null;

        try {
            genreList = new ArrayList<SlimGenre>(getDatabase().getGenres());
            //java.util.Collections.sort(artistList);
            top.removeAllChildren();

            for (SlimGenre g : genreList) {
                genreNode = new DefaultMutableTreeNode(g);
                top.add(genreNode);
                albumNode = new DefaultMutableTreeNode("Temp");
                genreNode.add(albumNode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void refreshComponents() {
        createArtistNodes(topArtistNode);
        createYearNodes(topYearNode);
        createGenreNodes(topGenreNode);
    }

    private void nodeArtistSelected(TreeSelectionEvent tse) {
        TreePath selectedPath = artistTree.getSelectionPath();

        try {
            Object selObject =
                    ((DefaultMutableTreeNode) selectedPath.getLastPathComponent()).getUserObject();
            if (selectedPath.getPathCount() == 2) {
                SlimArtist artist = (SlimArtist) selObject;
                songListTablePanel.setProgressBarVisible(true);
                songListTablePanel.setArtist(artist);
                songListTablePanel.setProgressBarVisible(false);
            } else if (artistTree.getSelectionPath().getPathCount() == 3) {
                loadAlbum((SlimAlbum) selObject);
            }
        } catch (Exception e) {
        }
    }

    private void nodeYearSelected(TreeSelectionEvent tse) {
        TreePath selectedPath = yearTree.getSelectionPath();

        try {
            Object selObject =
                    ((DefaultMutableTreeNode) selectedPath.getLastPathComponent()).getUserObject();
            if (selectedPath.getPathCount() == 2) {
                String year = (String) selObject;
                songListTablePanel.setProgressBarVisible(true);
                songListTablePanel.setYear(year);
                songListTablePanel.setProgressBarVisible(false);
            } else if (yearTree.getSelectionPath().getPathCount() == 3) {
                loadAlbum((SlimAlbum) selObject);
            }
        } catch (Exception e) {
        }
    }

    private void nodeGenreSelected(TreeSelectionEvent tse) {
        TreePath selectedPath = genreTree.getSelectionPath();

        try {
            Object selObject =
                    ((DefaultMutableTreeNode) selectedPath.getLastPathComponent()).getUserObject();
            if (selectedPath.getPathCount() == 2) {
                SlimGenre genre = (SlimGenre) selObject;
                songListTablePanel.setProgressBarVisible(true);
                songListTablePanel.setGenre(genre);
                songListTablePanel.setProgressBarVisible(false);
            } else if (artistTree.getSelectionPath().getPathCount() == 3) {
                loadAlbum((SlimAlbum) selObject);
            }
        } catch (Exception e) {
        }
    }

    public SlimDatabase getDatabase() {
        return database;
    }

    public void setDatabase(SlimDatabase database) {
        this.database = database;
    }

    public SlimPlaylist getPlaylist() {
        return playlist;
    }

    public void setPlaylist(SlimPlaylist playlist) {
        this.playlist = playlist;
    }

    private class ExplorerSelectPanel extends JPanel {

        private Image image;

        public ExplorerSelectPanel() {
            try {
                image = ImageIO.read(ExplorerButton.class.getResourceAsStream("/resources/slimserver/explorer_button_panel_background.png"));
            } catch (IOException ex) {
                Logger.getLogger(ExplorerListPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(image, 0, 0, this);
        }
    }

    private class ExplorerButton extends JButton {

        private Image image;
        private Image unSelectedimage;
        private Image selectedImage;

        public ExplorerButton() {
            try {
                unSelectedimage = ImageIO.read(ExplorerButton.class.getResourceAsStream("/resources/slimserver/explorer_button_background.png"));
                selectedImage = ImageIO.read(ExplorerButton.class.getResourceAsStream("/resources/slimserver/explorer_button_selected_background.png"));
            } catch (IOException ex) {
                Logger.getLogger(ExplorerListPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
            setContentAreaFilled(false);
            setUnselectedBackground();
            setBorder(BorderFactory.createEtchedBorder(Color.GRAY, Color.GRAY));
        }

        @Override
        public void paintComponent(Graphics g) {
            g.drawImage(image, 0, 0, this);
            super.paintComponent(g);
        }

        public void setSelectedBackground() {
            image = selectedImage;
            repaint();
        }

        public void setUnselectedBackground() {
            image = unSelectedimage;
            repaint();
        }
    }

    private class ExplorerPanel extends JPanel {

        public ExplorerPanel() {
            setBackground(ColorProperties.PANEL_COVER_ART_BACKGROUND);
        }
    }

    private void showList(String card) {
        CardLayout cl = (CardLayout) jPanel3.getLayout();
        cl.show(jPanel3, card);
        listChanged(card);
    }

    public void listChanged(String list) {
        setCardShowing(list);

        if (CARD_ARTIST.equalsIgnoreCase(list)) {
            int oldIndex = artistTree.getSelectionRows() == null ? 0 : artistTree.getSelectionRows()[0];

            if (oldIndex == -1) {
                oldIndex = 0;
            }

            artistTree.setSelectionRow(-1);
            artistTree.setSelectionRow(oldIndex);
        //loadArtistAlbums(true);
        } else if (CARD_YEAR.equalsIgnoreCase(list)) {
            int oldIndex = yearTree.getSelectionRows()== null ? 0 : yearTree.getSelectionRows()[0];

            if (oldIndex == -1) {
                oldIndex = 0;
            }

            yearTree.setSelectionRow(-1);
            yearTree.setSelectionRow(oldIndex);
        //loadYearAlbums(true);
        } else {
            int oldIndex = genreTree.getSelectionRows()== null ? 0 : genreTree.getSelectionRows()[0];

            if (oldIndex == -1) {
                oldIndex = 0;
            }

            genreTree.setSelectionRow(-1);
            genreTree.setSelectionRow(oldIndex);

        //loadGenreAlbums(true);
        }
    }

    /**
     * @return the cardShowing
     */
    public String getCardShowing() {
        return cardShowing;
    }

    /**
     * @param cardShowing the cardShowing to set
     */
    public void setCardShowing(String cardShowing) {
        this.cardShowing = cardShowing;
    }
}
